//
//  XYPlayTools.m
//  Player
//
//  Created by 岁变 on 16/9/14.
//  Copyright © 2016年 岁变. All rights reserved.
//

#import "XYPlayTools.h"

static XYPlayTools *xyp = nil;

@interface XYPlayTools ()

@property (nonatomic, strong) NSTimer *timer;

@end

@implementation XYPlayTools


//单例方法创建
+ (instancetype)shareMyPlayer {
    if (xyp == nil) {
        static dispatch_once_t once_token;
        dispatch_once(&once_token, ^{
            xyp = [[XYPlayTools alloc] init];
        });
        
    }
    return xyp;
}

// AVPlayer并没有通过block或者代理向我们返回这一状态(事件),而是向通知中心注册了一条通知(AVPlayerItemDidPlayToEndTimeNotification),我们也只有这一条途径获取播放结束这一事件.
// 所以,在我们创建好一个播放器时([[AVPlayer alloc] init]),应该立刻为通知中心添加观察者,来观察这一事件的发生.
// 这个动作放到init里,最及时也最合理.

- (instancetype)init {
    
    self = [super init];
    if (self) {
        _myPlayer = [[AVPlayer alloc] init];
        
        //创建播放器立刻为通知中心添加观察者
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endOfPlay:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    }
    return self;
}


//播放结束后的方法, 由代理方法具体实现行为
- (void)endOfPlay:(NSNotification *)sender {
    [self musicPause];
    [self.delegate endOfPlayAction];
}


//准备播放, 我们在外部调用播放器时, 不会调用 "直接播放", 而是调用这个"准备播放" , 当他准备好了 就直接播放.
- (void)musciPreparePlay {
    
    if (self.myPlayer.currentItem) {
        [self.myPlayer.currentItem removeObserver:self forKeyPath:@"status"];
    }
    
    AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:_mp3URL]];
    
    [item addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
    [self.myPlayer replaceCurrentItemWithPlayerItem:item];
    
}

//观察者的处理方法, 观察的是Item的Status状态
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    
    if ([keyPath isEqualToString:@"status"]) {
        switch ([[change valueForKey:@"new"] integerValue]) {
            case AVPlayerItemStatusUnknown:
                NSLog(@"未知的错误");
                break;
            case AVPlayerItemStatusReadyToPlay:
                [self musicPlay];
                break;
            case AVPlayerItemStatusFailed:
                NSLog(@"准备失败");
            default:
                break;
        }
    }
}


//播放
- (void)musicPlay {
    //如果计时器已经存在, 说明已经在播放中, 直接返回.
    //对于已经存在的计时器, 只有musicpause方法才会停止和注销
    if (self.timer != nil) {
        return;
    }
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
    [self.myPlayer play];
}

- (void)timerAction:(NSTimer *)sender {
    
    //计时器的处理方法中, 不断的调用代理方法, 将播放进度返回出去.
    [self.delegate getCurrentTime:[self valueToString:[self getCurrentTime]] totleTime:[self valueToString:[self getTotleTime]] progress:[self getProgress]];
    
}


//暂停
- (void)musicPause {
    
    [self.timer invalidate];
    self.timer = nil;
    [self.myPlayer pause];
}


//跳转方法
- (void)seekToTimeWithValue:(CGFloat)value {
    
    //先暂停
    [self musicPause];
    
    //跳转
    [self.myPlayer seekToTime:CMTimeMake(value *[self getTotleTime], 1) completionHandler:^(BOOL finished) {
        
        if (finished == YES) {
            [self musicPlay];
        }
    }];
}

//获取当前的播放时间
- (NSInteger)getCurrentTime {
    if (self.myPlayer.currentItem) {
        
        //用value/scale, 就是AVPlayer计算时间的算法, 它就是这么规定的.
        //下同
        return self.myPlayer.currentTime.value / self.myPlayer.currentTime.timescale;
    }
    return 0;
}


//获取总时长
- (NSInteger)getTotleTime {
    CMTime totleTime = [self.myPlayer.currentItem duration];
    if (totleTime.timescale == 0) {
        return 1;
    } else {
        
        return totleTime.value / totleTime.timescale;
    }
}

//获取当前播放进度
- (CGFloat)getProgress {
    return (CGFloat)[self getCurrentTime] / (CGFloat)[self getTotleTime];
}

//将整数秒转换成00:00格式字符串
- (NSString *)valueToString:(NSInteger)value {
    
    return [NSString stringWithFormat:@"%.2ld:%.2ld", value/60, value%60];
    
}








@end
